﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Types
{
    /// <summary>
    /// 
    /// </summary>
    public class Point3d : ICloneable
    {
        protected int m_nX = 0;
        protected int m_nY = 0;
        protected int m_nZ = 0;

        protected Point3d m_pt3dMin = null;
        protected Point3d m_pt3dMax = null;

        /// <summary>
        /// Initializes a new instance of the <see cref="Point3d"/> class.
        /// </summary>
        public Point3d()
        {
            m_nX = 0;
            m_nY = 0;
            m_nZ = 0;

        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Point3d"/> class.
        /// </summary>
        /// <param name="_point3d">The _point3d.</param>
        internal Point3d(Point3d _point3d)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Point3d"/> class.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <param name="z">The z.</param>
        public Point3d(int x, int y, int z)
        {
            m_nX = x;
            m_nY = y;
            m_nZ = z;
        }

        /// <summary>
        /// Gets or sets the min.
        /// </summary>
        /// <value>The min.</value>
        public Point3d Min
        {
            get { return m_pt3dMin; }
            set { m_pt3dMin = value; }
        }

        /// <summary>
        /// Gets or sets the max.
        /// </summary>
        /// <value>The max.</value>
        public Point3d Max
        {
            get { return m_pt3dMax; }
            set { m_pt3dMax = value; }
        }

        /// <summary>
        /// Adds the specified _point3d.
        /// </summary>
        /// <param name="_point3d">The _point3d.</param>
        /// <param name="_nX">The _n X.</param>
        /// <param name="_nY">The _n Y.</param>
        /// <param name="_nZ">The _n Z.</param>
        /// <returns></returns>
        public static Point3d Add(Point3d _point3d, int _nX, int _nY, int _nZ)
        {
            return new Point3d(_point3d.X, _point3d.Y, _point3d.Z);
        }

        /// <summary>
        /// Subtracts the specified _point3d.
        /// </summary>
        /// <param name="_point3d">The _point3d.</param>
        /// <param name="_nX">The _n X.</param>
        /// <param name="_nY">The _n Y.</param>
        /// <param name="_nZ">The _n Z.</param>
        /// <returns></returns>
        public static Point3d Subtract(Point3d _point3d, int _nX, int _nY, int _nZ)
        {
            return new Point3d(_point3d.X, _point3d.Y, _point3d.Z);
        }

        /// <summary>
        /// Adds the specified _point3d.
        /// </summary>
        /// <param name="_point3d">The _point3d.</param>
        /// <param name="_size3d">The _size3d.</param>
        /// <returns></returns>
        public static Point3d Add(Point3d _point3d, Size3d _size3d)
        {
            return new Point3d(_point3d.X+_size3d.Depth, _point3d.Y+_size3d.Width, _point3d.Z+_size3d.Height);
        }

        /// <summary>
        /// Subtracts the specified _point3d.
        /// </summary>
        /// <param name="_point3d">The _point3d.</param>
        /// <param name="_size3d">The _size3d.</param>
        /// <returns></returns>
        public static Point3d Subtract(Point3d _point3d, Size3d _size3d)
        {
            return new Point3d(_point3d.X - _size3d.Depth, _point3d.Y - _size3d.Width, _point3d.Z - _size3d.Height);
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return X.ToString() + " " + Y.ToString() + " " + Z.ToString();
        }

        /// <summary>
        /// Gets or sets the X.
        /// </summary>
        /// <value>The X.</value>
        public int X
        {
            get { return m_nX; }
            set
            {
                m_nX = value;
                if (m_nX < Min.X) m_nX = Min.X;
                if (m_nX > Max.X) m_nX = Max.X;
            }
        }

        public static Point3d Empty
        {
            get { return new Point3d(0, 0, 0); }
        }

        /// <summary>
        /// Gets or sets the Y.
        /// </summary>
        /// <value>The Y.</value>
        public int Y
        {
            get { return m_nY; }
            set
            {
                m_nY = value;
                if (m_nY < Min.Y) m_nY = Min.Y;
                if (m_nY > Max.Y) m_nY = Max.Y;
            }
        }

        /// <summary>
        /// Gets or sets the Z.
        /// </summary>
        /// <value>The Z.</value>
        public int Z
        {
            get { return m_nZ; }
            set
            {
                m_nZ = value;
                if (m_nZ < Min.Z) m_nZ = Min.Z;
                if (m_nZ > Max.Z) m_nZ = Max.Z;
            }
        }

        /// <summary>
        /// Compares the specified x.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <param name="z">The z.</param>
        /// <returns></returns>
        public bool Compare(int x, int y, int z)
        {
            return (x == m_nX && y == m_nY && z == m_nZ);
        }

        /// <summary>
        /// Compares the specified pt.
        /// </summary>
        /// <param name="pt">The pt.</param>
        /// <returns></returns>
        public bool Compare(Point3d pt)
        {
            return (m_nX == pt.X && m_nY == pt.Y && m_nZ == pt.Z);
        }

        #region ICloneable Members

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public object Clone()
        {
            return new Point3d(this);
        }

        #endregion
    }
}
